﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Core
{
    public class IdentityScope:IDisposable
    {
        private WindowsImpersonationContext impersonationContext;
        private const int LOGON32_LOGON_INTERACTIVE = 9; 
        private const int LOGON32_PROVIDER_DEFAULT = 0;
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        private static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
        private extern static int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool RevertToSelf();
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        private bool disposed;

        public IdentityScope(string userName, string domain, string password)
        {
            WindowsIdentity wi; 
            IntPtr token = IntPtr.Zero; 
            IntPtr tokenDuplicate = IntPtr.Zero; 
            if (RevertToSelf()) 
            { 
                if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) 
                { 
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
                    { 
                        wi = new WindowsIdentity(tokenDuplicate); 
                        impersonationContext = wi.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(tokenDuplicate);
                            CloseHandle(token);
                            return;
                        }
                        else
                        {
                            if (tokenDuplicate != IntPtr.Zero)
                                CloseHandle(tokenDuplicate);
                            if (token != IntPtr.Zero)
                                CloseHandle(token);
                            return;
                        }
                    } 
                    else 
                    { 
                        if (token != IntPtr.Zero) 
                            CloseHandle(token); 
                        return; 
                    } 
                } 
                else
                    return;
            } 
            else 
                return;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                RevertToSelf();
                disposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

    }
}
